import numpy as np
import time
import os
import requests
import json
from .config_manager import config_manager

class SemanticAnalyzer:
    """AI大模型语义理解模块，负责场景分析与推理"""
    
    def __init__(self, api_key=None, model=None, use_api=None):
        """初始化语义分析器
        
        Args:
            api_key: OpenAI API密钥，如果为None则尝试从环境变量获取
            model: 使用的OpenAI模型名称，如果为None则从环境变量获取
            use_api: 是否使用API调用，默认为None则从环境变量获取
        """
        # 配置API参数，优先级：显式参数 > 环境变量 > 默认值
        self.use_api = use_api if use_api is not None else (
            os.getenv("USE_LLM_API", "true").lower() == "true")
        self.model = model or os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
        self.api_key = api_key or os.getenv("OPENAI_API_KEY")
        self.api_base_url = os.getenv("OPENAI_API_URL", "https://api.openai.com/v1/chat/completions")
        
        # 检查API密钥
        if self.use_api and not self.api_key:
            print("警告: 未提供OpenAI API密钥，将使用本地规则进行分析")
            self.use_api = False
        
        print("语义分析器初始化完成")
        if self.use_api:
            print(f"  - 将使用OpenAI API进行语义分析 (模型: {self.model})")
            print(f"  - API基础URL: {self.api_base_url}")
        else:
            print("  - 将使用本地规则进行语义分析")
    
    def _call_openai_api(self, prompt, max_tokens=200, temperature=0.7):
        """调用OpenAI API进行文本生成
        
        Args:
            prompt: 提示文本
            max_tokens: 最大生成token数
            temperature: 生成多样性控制参数
        
        Returns:
            生成的文本内容
        """
        if not self.use_api or not self.api_key:
            return "[OpenAI API未配置，无法进行高级语义分析]"
        
        try:
            headers = {
                "Content-Type": "application/json",
                "Authorization": f"Bearer {self.api_key}"
            }
            
            data = {
                "model": self.model,
                "messages": [{"role": "user", "content": prompt}],
                "max_tokens": max_tokens,
                "temperature": temperature
            }
            
            # 发送API请求
            response = requests.post(
                self.api_base_url,
                headers=headers,
                data=json.dumps(data),
                timeout=10  # 10秒超时
            )
            
            # 检查响应状态
            if response.status_code == 200:
                result = response.json()
                return result["choices"][0]["message"]["content"].strip()
            else:
                print(f"OpenAI API请求失败: {response.status_code} - {response.text}")
                return f"[API请求失败: {response.status_code}]"
        except Exception as e:
            print(f"OpenAI API调用异常: {str(e)}")
            return f"[API调用异常: {str(e)}]"
    
    def analyze_scene(self, frame, detections, model_names=None):
        """分析场景语义
        
        Args:
            frame: 输入图像
            detections: 检测结果
            model_names: 模型类别名称字典
        
        Returns:
            场景分析描述
        """
        if detections is None or len(detections) == 0:
            return "场景中未检测到明显目标"
        
        # 统计各类别物体数量
        class_counts = self._count_objects_by_class(detections, model_names)
        
        # 生成场景描述
        description = "场景分析：\n"
        for class_name, count in class_counts.items():
            description += f"- 检测到{count}个{class_name}\n"
        
        # 简单的场景判断
        scene_type = self._infer_scene_type(class_counts)
        description += scene_type
        
        # 生成一些简单的推理
        inferences = self._make_inferences(class_counts)
        description += inferences
        
        # 如果使用API，获取更高级的语义理解
        if self.use_api:
            # 构建提示文本
            prompt = f"请分析一个视频监控场景，其中包含以下物体：{class_counts}。\n"
            prompt += "请从以下几个方面进行分析：\n"
            prompt += "1. 这个场景可能是什么地方？\n"
            prompt += "2. 场景中可能正在发生什么事情？\n"
            prompt += "3. 是否有任何异常或需要注意的情况？\n"
            prompt += "4. 如果这个场景需要监控，您有什么建议？\n"
            prompt += "请用简洁明了的中文回答。\n"
            
            # 调用API获取高级分析结果
            advanced_analysis = self._call_openai_api(prompt, max_tokens=300)
            description += "\n高级语义分析 (OpenAI):\n"
            description += advanced_analysis
        
        return description
    
    def _count_objects_by_class(self, detections, model_names=None):
        """统计各类别物体的数量
        
        Args:
            detections: 检测结果
            model_names: 模型类别名称字典
        
        Returns:
            类别计数字典
        """
        class_counts = {}
        
        # 检查是否有class_id属性
        if hasattr(detections, 'class_id'):
            for class_id in detections.class_id:
                # 获取类别名称
                if model_names and class_id < len(model_names):
                    english_class_name = model_names[class_id]
                    # 使用配置管理器将英文类别名转换为中文
                    class_name = config_manager.get_chinese_class_name(english_class_name)
                else:
                    # 尝试从detections对象中获取模型名称
                    class_name = f"类别{class_id}"
                
                class_counts[class_name] = class_counts.get(class_name, 0) + 1
        
        return class_counts
    
    def _infer_scene_type(self, class_counts):
        """推断场景类型
        
        Args:
            class_counts: 类别计数字典
        
        Returns:
            场景类型描述
        """
        # 人员密集场景判断
        if "人员" in class_counts and class_counts["人员"] > 3:
            return "当前场景人员较多，可能是公共场所\n"
        elif "人员" in class_counts and class_counts["人员"] == 1:
            return "当前场景有1人，可能是个人场景\n"
        
        # 交通场景判断
        if "车辆" in class_counts and class_counts["车辆"] > 2:
            return "当前场景车辆较多，可能是交通场景\n"
        elif ("车辆" in class_counts or "卡车" in class_counts) and sum([class_counts.get(v, 0) for v in ["车辆", "卡车", "公交车"]]) > 1:
            return "当前场景有车辆，可能是道路或停车场\n"
        
        # 室内场景判断
        indoor_objects = ["椅子", "沙发", "餐桌", "电视", "笔记本电脑"]
        indoor_count = sum([class_counts.get(obj, 0) for obj in indoor_objects])
        if indoor_count > 2:
            return "当前场景有较多室内物品，可能是室内环境\n"
        
        # 其他场景
        return "无法确定具体场景类型\n"
    
    def _make_inferences(self, class_counts):
        """基于检测结果进行简单推理
        
        Args:
            class_counts: 类别计数字典
        
        Returns:
            推理结果描述
        """
        inferences = "简单推理：\n"
        
        # 人员相关推理
        if "person" in class_counts:
            if class_counts["person"] > 5:
                inferences += "- 人员密度较高，请注意安全\n"
            elif class_counts["person"] == 0:
                inferences += "- 当前场景无人\n"
        
        # 车辆相关推理
        vehicle_classes = ["car", "truck", "bus", "motorcycle"]
        total_vehicles = sum([class_counts.get(v, 0) for v in vehicle_classes])
        if total_vehicles > 5:
            inferences += f"- 检测到{total_vehicles}辆车，可能存在交通压力\n"
        
        # 物体间关系推理
        if "person" in class_counts and "car" in class_counts:
            inferences += "- 场景中同时存在人和车辆，请注意行人安全\n"
        
        # 特殊物品推理
        special_items = ["knife", "gun", "bomb"]
        for item in special_items:
            if item in class_counts:
                inferences += f"- 检测到{item}，请注意安全\n"
        
        if len(inferences) == len("简单推理：\n"):
            inferences += "- 未发现明显异常情况\n"
        
        # 如果使用API，获取更深入的推理
        if self.use_api:
            prompt = f"基于以下物体检测结果：{class_counts}，\n"
            prompt += "请进行更深入的推理分析，包括但不限于：\n"
            prompt += "1. 物体之间可能存在的关系\n"
            prompt += "2. 场景中可能存在的潜在风险\n"
            prompt += "3. 该场景下的安全建议\n"
            prompt += "请用简洁明了的中文回答，每条建议前加'-'符号。\n"
            
            advanced_inferences = self._call_openai_api(prompt, max_tokens=200)
            inferences += "\n高级推理 (OpenAI):\n"
            inferences += advanced_inferences
        
        return inferences
        
    def detect_anomalies(self, class_counts, historical_data=None):
        """检测场景中的异常情况
        
        Args:
            class_counts: 类别计数字典或检测结果对象
            historical_data: 历史数据，用于比较（可选）
        
        Returns:
            异常列表，每个异常是包含type和message的字典
        """
        anomalies = []
        
        # 确保输入是类别计数字典
        if hasattr(class_counts, 'class_id'):
            # 如果传入的是detections对象，先统计类别
            temp_counts = {}
            for class_id in class_counts.class_id:
                # 尝试从检测器中获取模型名称
                temp_counts[class_id] = temp_counts.get(class_id, 0) + 1
            class_counts = temp_counts
        
        # 人员异常检测
        if "person" in class_counts:
            if class_counts["person"] > 10:
                anomalies.append({
                    "type": "crowd",
                    "message": "人员过于密集，存在安全隐患"
                })
            if class_counts["person"] > 20:
                anomalies.append({
                    "type": "crowd", 
                    "severity": "high", 
                    "message": "人员极为密集，存在严重安全隐患"
                })
        
        # 车辆异常检测
        if "car" in class_counts:
            if class_counts["car"] > 10:
                anomalies.append({
                    "type": "traffic_congestion",
                    "message": "车辆拥堵，交通状况不佳"
                })
            if class_counts["car"] > 15:
                anomalies.append({
                    "type": "traffic", 
                    "severity": "medium", 
                    "message": "车辆过多，严重拥堵"
                })
        
        # 特殊物品异常检测
        dangerous_items = ["knife", "gun", "bomb"]
        for item in dangerous_items:
            if item in class_counts:
                anomalies.append({
                    "type": "dangerous_object",
                    "message": f"检测到危险物品: {item}"
                })
        
        # 如果使用API，进行更高级的异常检测
        if self.use_api:
            prompt = f"请分析以下场景中的异常情况：{class_counts}。\n"
            prompt += "请识别任何可能的异常行为、异常聚集或异常物体组合，并按以下格式返回：\n"
            prompt += "- 类型: [异常类型]\n"
            prompt += "  描述: [异常详细描述]\n"
            prompt += "  严重性: [低/中/高]\n"
            prompt += "如果没有异常，请返回'未检测到明显异常'。\n"
            
            api_anomalies = self._call_openai_api(prompt, max_tokens=300)
            
            # 处理API返回的异常结果
            if api_anomalies and "未检测到明显异常" not in api_anomalies:
                # 简单解析API返回的异常信息
                for line in api_anomalies.split('\n'):
                    if line.startswith('- 类型:'):
                        anomaly_type = line.replace('- 类型:', '').strip()
                    elif line.startswith('  描述:'):
                        description = line.replace('  描述:', '').strip()
                    elif line.startswith('  严重性:'):
                        severity = line.replace('  严重性:', '').strip()
                        anomalies.append({
                            "type": anomaly_type,
                            "message": description,
                            "severity": severity,
                            "source": "openai"
                        })
        
        # 如果有历史数据，可以进行更复杂的异常检测
        if historical_data:
            # 这里可以实现基于历史数据的异常检测算法
            pass
        
        return anomalies

# 注意：不创建全局实例，在实际使用时通过导入类并实例化
# 遵循Java风格的实例化模式，在使用时才创建实例